﻿using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using LimaLims.Application.Service.Base.Dto;
using LimaLims.Application.Service.Basic.Dto;
using LimaLims.Application.Service.Sys;
using LimaLims.Core;
using LimaLims.Core.Entity.Basic;
using LimaLims.Core.Entity.TestCenter;
using LimaLims.Core.Enum;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.CodeAnalysis;
using Microsoft.EntityFrameworkCore;
namespace LimaLims.Application.Service.Basic
{
    /// <summary>
    /// 产品服务
    /// </summary>
    [ApiDescriptionSettings(Name = "Product", Order = 153)]
    [Route("api")]
    public class ProductService : IProductService, IDynamicApiController, ITransient
    {

        private readonly IRepository<Product> _productRep;  // 产品表仓储
        private readonly IRepository<ExperimentTask> _experimentTaskRep;
        private readonly IGenerateCodeUtilService _generateCodeUtilService;//编码规则

        public ProductService(IRepository<Product> productRep, IRepository<ExperimentTask> experimentTaskRep, IGenerateCodeUtilService generateCode)
        {
            _productRep = productRep;
            _experimentTaskRep = experimentTaskRep;
            _generateCodeUtilService = generateCode;
        }

        /// <summary>
        /// 新增
        /// </summary>
        [HttpPost("product/add")]
        public async Task Add(AddProductInput input)
        {
            var isExist = await _productRep.DetachedEntities.AnyAsync(u => u.Name == input.Name && u.Code == input.Code);
            if (isExist)
                throw Oops.Oh("已存在相同名称和编号的产品！");

            if (string.IsNullOrWhiteSpace(input.Code))
            {
                input.Code = await _generateCodeUtilService.GenerateCode(BusinessType.Product);
            }
            var product = input.Adapt<Product>();

            await product.InsertAsync();
        }

        [HttpPost("product/delete")]
        public async Task Delete(long id)
        {
            var product = await _productRep.FirstOrDefaultAsync(u => u.Id == id);
            if (product == null)
                throw Oops.Oh("不存在此数据");

            var tasks = _experimentTaskRep.DetachedEntities.Count(s => s.TargetId == product.Id);

            if (tasks > 0)
                throw Oops.Oh("此商品已关联试验任务信息，请勿直接删除！");

            await product.DeleteAsync();
        }

        [HttpGet("product/detail")]
        public async Task<Product> Detail(long id)
        {
            var product = await _productRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == id);
            if (product == null)
                throw Oops.Oh("不存在此数据");

            return product;
        }


        /// <summary>
        /// 试验报告
        /// </summary>
        [HttpGet("product/getProductReports")]
        public async Task<List<ProductReportDetail>> GetProductReports(long productId)
        {
            var product = await _productRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == productId);
            if (product == null)
                throw Oops.Oh("不存在此数据");

            var tasks = await _experimentTaskRep.DetachedEntities.Where(s => s.TargetId == product.Id)
                .OrderByDescending(s => s.CreatedTime)
                .Select(s => new ProductReportDetail
                {
                    TaskId = s.Id,
                    ProductId = s.TargetId,
                    FactoryNumbe = product.FactoryNumbe,
                    ProductCode = s.TargetCode,
                    TaskCode = s.TaskCode,
                    TaskStatus = s.Status,
                    ActualStartTime = s.ActualStartTime,
                    ActualEndTime = s.ActualEndTime,
                    ExperimentUserName = s.ExperimentUserName,
                    Result=s.Result,
                    ReportUrl = s.ReportUrl,
                }).ToListAsync();

            return tasks;
        }


        [HttpPost("product/edit")]
        public async Task Edit(EditProductInput input)
        {
            var product = await _productRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
            if (product == null)
                throw Oops.Oh("不存在此数据！");

            var isExist = await _productRep.DetachedEntities.AnyAsync(u => u.Name == input.Name && u.Code == input.Code && u.Id != input.Id);
            if (isExist)
                throw Oops.Oh("已存在相同名称和编号的产品");

            var productModel = input.Adapt<Product>();

            await productModel.UpdateAsync();
        }
        /// <summary>
        /// 下拉数据
        /// </summary>
        /// <returns></returns>
        [HttpGet("product/selectList")]
        public async Task<List<SelectDto>> SelectList()
        {
            var list = await _productRep.DetachedEntities.Where(s => s.ValidStatus).OrderBy(s => s.Sort).ToListAsync();
            return list.Select(x => new SelectDto
            {
                Value = x.Id,
                Label = $"{x.Code}-{x.Name}"
            }).ToList();
        }

        [HttpGet("product/page")]
        public async Task<PageResult<ProductOutput>> QueryPage([FromQuery] ProductPageInput input)
        {
            var name = !string.IsNullOrEmpty(input.SearchValue?.Trim());
            var factoryNumbe = !string.IsNullOrEmpty(input.FactoryNumbe?.Trim());
            var category = input.CategoryId.HasValue && input.CategoryId != 0;
            var products = await _productRep.DetachedEntities
                                         .Include(s => s.Category).Include(s => s.ProjectDrawing)
                                         .Where(name, u => u.Name.Contains(input.SearchValue.Trim()) || u.Code.Contains(input.SearchValue.Trim()))
                                         .Where(factoryNumbe, u => u.FactoryNumbe.Contains(input.FactoryNumbe.Trim()))
                                         .Where(input.ValidStatus.HasValue, u => u.ValidStatus == input.ValidStatus)
                                         .Where(input.ProjectDrawingId.HasValue, u => u.ProjectDrawingId == input.ProjectDrawingId)
                                         .Where(category, u => u.Category.Pids.Contains(input.CategoryId.ToString()) || u.CategoryId == input.CategoryId)
                                         .OrderByDescending(u => u.CreatedTime).ThenBy(u => u.Sort)
                                         .Select(u => new ProductOutput
                                         {
                                             Id = u.Id,
                                             Code = u.Code,
                                             Name = u.Name,
                                             ProjectName = u.ProjectDrawing.ProjectName,
                                             FactoryNumbe = u.FactoryNumbe,
                                             Specification = u.ProjectDrawing.Specification,
                                             Unit = u.ProjectDrawing.Unit,
                                             Remark = u.Remark,
                                             CategoryId = u.CategoryId,
                                             CategoryName = u.Category.Name,
                                             ValidStatus = u.ValidStatus,
                                             Sort = u.Sort,
                                             CreatedTime = u.CreatedTime,
                                             CreatedUserName = u.CreatedUserName,
                                             UpdatedTime = u.UpdatedTime,
                                             UpdatedUserName = u.UpdatedUserName
                                         }).ToADPagedListAsync(input.PageNo, input.PageSize);

            return products;
        }
    }
}
